package de.hska.reka.websockets.annotationProcessors;

import java.lang.reflect.Method;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import de.hska.reka.websockets.WebSocketServiceExporter;
import de.hska.reka.websockets.annotations.WebSocket;
import de.hska.reka.websockets.annotations.WebSocketMethod;
import de.hska.reka.websockets.annotations.WebSocketRef;

@Component
public class WebsocketAnnotationProcessor implements BeanPostProcessor,
		ApplicationContextAware {
	@Autowired
	private ApplicationContext applicationContext;

	public Object postProcessAfterInitialization(final Object bean,
			final String beanName) throws BeansException {
		System.out.println("processing " + bean.getClass());

		if (bean.getClass().isAnnotationPresent(WebSocket.class)) {
			final WebSocketServiceExporter exporter = new WebSocketServiceExporter();
			System.out.println("WebSocket present");
			ReflectionUtils.doWithMethods(bean.getClass(),
					new ReflectionUtils.MethodCallback() {
						public void doWith(Method method)
								throws IllegalArgumentException,
								IllegalAccessException {
							if (method
									.isAnnotationPresent(WebSocketMethod.class)) {
								exporter.addMethodToMap(method, beanName);
							}
						}
					});
			try {
				exporter.afterPropertiesSet();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} else if (bean.getClass().isAnnotationPresent(WebSocketRef.class)) {
			System.out.println("WebSocketRef present");
			final WebSocketServiceExporter exporter = (WebSocketServiceExporter) this.applicationContext
					.getBean(bean.getClass().getAnnotation(WebSocketRef.class)
							.beanRefName());
			ReflectionUtils.doWithMethods(bean.getClass(),
					new ReflectionUtils.MethodCallback() {
						public void doWith(Method method)
								throws IllegalArgumentException,
								IllegalAccessException {
							if (method
									.isAnnotationPresent(WebSocketMethod.class)) {
								exporter.addMethodToMap(method, beanName);
							}
						}
					});
		}
		return bean;
	}

	public Object postProcessBeforeInitialization(final Object bean,
			String beanName) throws BeansException {

		return bean;
	}

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		this.applicationContext = applicationContext;
	}

}
